{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bayesian Network Structure Learning\n",
    "\n",
    "author: Jacob Schreiber <br>\n",
    "contact: jmschreiber91@gmail.com\n",
    "    \n",
    "Learning the structure of Bayesian networks can be complicated for two main reasons: (1) difficulties in inferring causality and (2) the super-exponential number of directed edges that could exist in a dataset. The first issue presents itself when the structure lerning algorithm considers only correlation or another measure of co-occurrence to determine if an edge should exist. The first point presents challenges which deserve a far more in depth treatment unrelated to implementations in pomegranate, so instead this tutorial will focus on how pomegranate implements fast Bayesian network structure learning. It will also cover a new concept called the \"constraint graph\" which can be used to massively speed up structure search while also making causality assignment a bit more reasonable.\n",
    "\n",
    "### Introduction to Bayesian Network Structure Learning\n",
    "\n",
    "Most methods for Bayesian network structure learning (BNSL) can be put into one of the following three categories: \n",
    "\n",
    "(1) Search and Score: The most intuitive method is that of 'search and score,' where one searches over the space of all possible directed acyclic graphs (DAGs) and identifies the one that minimizes some objective function. Typical objective functions attempt to balance the log probability of the data given the model (the likelihood) with the complexity of the model to encourage sparser models. A naive implementation of this search is super-exponential in time with the number of variables, and becomes infeasible when considering even less than a dozen variables. However, dynamic programming can efficiently remove the many repeated calculations and reduce this to be simply exponential in time. This allows exact BNSL to scale to ~25-30 variables. In addition, the A\\* algorithm can be used to smartly search the space and reduce computational time even further by not even considering all possibile networks.\n",
    "\n",
    "(2) Constraint learning: These methods typically involve calculating some measure of correlation or co-occurrence to identify an undirected backbone of edges that could exist, and then prune these edges systematically until a DAG is reached. A common method is to iterate over all triplets of variables to identify conditional independencies that specify both presence and direction of the edges. This algorithm is asymptotically faster (quadratic in time) than search-and-score, but it does not have a simple probabilistic interpretation.\n",
    "\n",
    "(3) Approximate algorithms: In many real world examples, one wishes to merge the interpretability of the search and score method with the attractiveness of the task finishing before the universe ends. To this end, several heuristics have been developed with different properties to yield good structures in a reasonable amount of time. These methods include the Chow-Liu tree building algorithm, the hill-climbing algorithm, and optimal reinsertion, though there are others.\n",
    "\n",
    "pomegranate currently implements a search-and-score method based on the minimum description length score which utilizes the dynamic programming and A\\* algorithm (DP/A\\*), a greedy algorithm based off of DP/A\\*, and the Chow-Liu tree building algorithm, though there are plans to soon add other algorithms.\n",
    "\n",
    "### Structure Learning in pomegranate\n",
    "#### Exact Learning\n",
    "\n",
    "Structure learning in pomegranate is done using the `from_samples` method. All you pass in is the samples, their associated weights (if not uniform), and the algorithm which you'd like to use, and it will learn the network for you using the dynamic programming implementation. Lets see a quick synthetic example to make sure that appropriate connections are found. Lets add connections between variables 1, 3, 6, and variables 0 and 2, and variables 4 and 5."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Populating the interactive namespace from numpy and matplotlib\n",
      "((), (), (0,), (1,), (), (4,), (3,))\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPwAAADnCAYAAAA6ujs/AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAehUlEQVR4nO2df3AV1b3AP0EI+UkoJVCSlKRFUEmgSCIVFMY8cegMTgdMeSrQjk5HgTdqH9bXCmqtFtSx8ngKw1DfaKkFpg+ksa3TaYKjTMTIYFAqBKXEEVOSKGmDIYGb8CPn/XHYZG+C9XLv7tndu9/PzJ29d3ey57ufnO+e/XH2bIpSSiEIQigY5HUAgiCYQxJeEEKEJLwghAhJeEEIEZLwghAiJOEFIURIwgtCiJCEF4QQMdjrAKJQCo4ehaYmaG6G1lY9v6sLIhH9PT0d0tIgN1f/zsuD/HwoKoKUFC+i9idWf6r+Pu0uIdqn3SWITzv96yYM9Gm5hIE+feJSWnhBCBEpnnWtbWqCmhr9/c03oa4O6uv1njE/X+8dx4zRy4cM0XtP0HvTs2ehpUX/bm7W62ptheJiKCuDmTP1slmz9LrCgOXT7hIG+rS7hGifdpcQ7TOMLuGL6yYM9Gm5hIE+fVI3zSZ8YyNs2QKVlfrw6Prr9fwbboBrroGSEsjOjm/dHR1w8CC88w7s2qXn7d4NhYVwyy2waBGMHevARvgEyyVE+7S7hPh8dnToqd2n3SUkr88kr5vuJ3xVlZ4+9xy8/TYsXgzz5kF5ufvnNUppwZWVsHkzTJ8O992nl82Z427ZblFVFe0SzPi0u4Ron0F2CeGqm8otqquVmjZNqUmT9GfTJqUiEdeK+1IiER2DFc+0aTrGoGD36bVLpaJ9BtmlH3warJvOJ/zf/65URYVS48crtW2b46t3jG3bdIwVFTpmP2K59LtPu8sg+PSzS6VcrZvOXqXfsQNKS2HSJH2RY8ECR1fvKAsW6BgnTdIx79jhdUTR2F363afdZRB8+tkluFo35bacIIQJR44TVqzQn3HjlKqrc2SVRqmr07GvWOF1JJogu1RKfDqJ3aUDPhO7Sq8UPPUUrFypf3/+OeTkOLQrMszJk3DjjfoQCmDjRvMx2H0G2SVE+/TSJQTfp+USEvaZWNfae+6B2lro7NS/MzMTWp2nDBumb5NkZenfQ4bAunVmY7D7DLJLiPbppUsIvk/LJSTsM/5z+LVrYe9eff8yMzPYQi0yM+H0af3Zs0dvownWrh3oMxmwfFouTfq0XCaLTyvHEq2bcZ0I1NcrNWqUUkeOJHxO4VsaGpTKzdXb6iaWy2T2abk06TNZXSqVUN2M7xz+ppt0l8Bly+LbywSFDRvglVegutq9MiyXkNw+N2zQU1M+k9klxF035bacIISJSz4m2LlTqeJipc6fv+Q/TYT29naj5Sml9DYWF+ttdgO7S8M+u7u7VXd3t7kCrW005dMwZ86cUZ9//rm5AuN0eekt/IsvwtKlMMj9g4OWlhZaWlr4wQ9+wKuvvsqyZcuosR5bNMGgQfrQ8IUX3Fm/3aUBnwANDQ0sXLiQJ554gieeeMJImUDfNpryaZiVK1fyzDPPmCswXpcx7xpOn9af7GylOjoudX8UFzNnzlQzZ85U2y70e/70009Vfn6+amtrM1K+Ukpva3a23nYnMexSKd2q19fXq+nTp6tHHnlEPfLII8bK7iWJfFq8/fbb6oorrlAPP/yw2YLtLmP0GfuucP9+/Rk/vu9etYv84x//YPfu3ezevZvvfve7AIwePZpvfOMb1Fr3V02QlaW3ef9+Z9dr0KVFamoqEydOZPTo0cbKHEAS+QTo6uqiurqaG62OMSaxu4zRZ+wJX1+vP2Vl8YZ3Sbz33nvk5OSQk5PD0KFDe+fn5uayd+9eIzH0UlbWN4KMUxh06TuSyOf69etZ5uUdActljD5j72nX1qanhron7t+/n5EjRw6YP3LkSOrq6ozE0EtOTt/2O0VbW3C7eiZKkvjcu3cvhYWF5FoDqnrBJbqU23KCECJ8m/Dd3d0MHjyYwYOjD0JSU1MZ5MFVWEGw6O7upru7m8rKShb4+bn6ixD7If2IEXr60UcuhRJNfn4+x48fHzC/s7OTK664wkgMvbS3w4QJzq5zxAhjLn1HwH1uvPC0WktLCysvPCm6Z88e0tPTefzxxwH42c9+ZiSWS3UZe1NZXKw/hs6fr732Wk6cOMGJEyc4aw39Cxw7dowSa0RWU9TV6W13EoMufUfAfU6dOpWpU6dy5ZVXMmzYMIYNG0ZaWhqpqalkZ2eTHe/otvFguYzRZ+wt/JQpenrkiH7c0OXbH1dddRXl5eUA/OEPf+B73/sekUiEkydPcvvtt7tadhSdnXqbre13iilTjLnsz7lz51AevY4gGXzOvDC2vDUFaG5uJicnh+XLl7tadhRxuIw94a3B9m++GTZt0s8bu8yWC+OuL1++nM7OTlpbW1mzZk3UbTrX2bRJb7P95Q1OkJ5u1CWAUorKykr27NnTe7o0d+5crr32WiPlA0nl03PicXnJvXs86q988uRJo+UppZK6L71xkrwvvXGM9aWfPVu/YudXv7rkP00Eo+dFFhs36tcKzZ7tzvrtLg37NM7GjWZ9JjtxupT7W4IQJuI6nKiv1yNuNDTE9eeBoKFBj5xy8KC75Vguk9mn5dKkz2R1qVRCdTP+UWvXroWtW/VbNp2+AOMlXV16OnMmLFwIJq66WuOTJatPyyWY82m5hOT1GYfL+EetXb4cGhogIyM5Rq0FOHUKZszQ32fNMlM5oa8cu8+gu4Q+nyZdQnTdhOTweeqUniboM/G3x951Fxw4oL9XV+shdYNIezsMHw5PP61/P/CA+28QvRiWzyC7hGifXrqE4Pu0XELiPh05p5A3zzhLkF0qJT6dxOE3zzj79tiXX9YXE37+c6VMjpcWL93dOtZRo3TsfsLuMgg+LZdB8Ol3l0q5VjfltpwghAhnE76iAvbt0+dMJSWwfbujq3eU7dt1jAcO6JgrKryOKBq7S7/7tLsMgk8/uwR366Zjxwr9qa5Wato0pSZN0p9f/1qpSMS14r6USETHYMUzbZqOMSjYfXrtUqlon0F26QefButm4lfpv4yqKj1dt06/3G/xYpg3D8rL3b9yqxS88YZ+Q8fmzfqWxr336mVz5rhbtltUVUW7BDM+7S4h2meQXUKo6qb7CW+nsRG2bIHKSjh6FK67Ts8vL9eD8ZWUxH/rpKNDHwLV1WmRAG+9BUVFMH8+LFoEY8c6sRX+wHIJ0T7tLiE+nx0demr3aXcJyeszyeum2YS309zc1xOqpkafq9TXw8iR+qGAvDz9IARAaiqkpem9biQCZ85AS0vfepqbobVV/1NKS3XHBNA9kvLzzW+bF1g+7S5hoE+7S4j2aXcJ0T7D6BK+uG7CQJ+WSxjo0yd107uEvxhKwSefQFNTdMWLRPjd3r0opbj929/WXSWtkULz8rS4wkJvOnf4Fevf2t+nzSUQ7dPuEsSnnf51Ewb47HUJA336xKXclhOEEBF/X3o3SEnR5zVFRQMWHX7sMXp6euDHPzYeViCxWpSL+Ox1CeIzVpKkbkoLLwghwl8t/L8gJSVFxqN3CHHpLEHyGZiEV0r1HYYKCSEunSVIPoOxWxIEwREC08IPGjTIu7HUkwxx6SxB8hmYhO/p6QmMVL8jLp0lSD7lkF4QQoQkvCCECEl4QQgRkvCCECIk4QUhRATmKn2Qbn34HXHpLEHyGZiED9KtD78jLp0lSD7lkF4QQoQkvCCECEl4QQgRkvCCECIk4QUhREjCC0KICMxtuSDd6/Q74tJZguRTWnhBCBGBaeGD1LnB74hLZwmST2nhBSFESMILQoiQhBeEECEJLwghwrcX7davX09tbW3v78OHD6OU4siRIwDMmDEDgKVLlzJ4sG83wzfYfVougSif4jI21q9fDzDAp+US/OtTWnhBCBH+el20jZQYX6/r0/B9Ryw+xWVsBLlu+raFX716NWlpaaSlpQ1YlpaWxqpVq1i1apUHkQUTy+fFsHwKsbF69eov9GnVWb/69G0L39jYyIQJEwDo7u6OWjZ06FAOHz4MQGFhofHYgojls79L6PMpLmOjsbER4KI+hw4dCuBbn75NeIDJkycDcODAgaj5JSUlA+YJX87kyZMv6k18xsfFfJaUlAAD66xf8O0hPcDdd9/N3XffTUZGRu+8jIwMlixZ4mFUwaW/SxCfifBFddPPPn3dwre2tgJQUFDAmTNnAEhNTeXYsWPk5uZ6GVogaW1tjXIJ4jMR+vu0XAK+9enrFj43N5fc3FzKysp655WWlvpWpt/p7xLEZyJ8Ud30s09fJ7wgCM4SiIRfsmQJWVlZZGVlsXTpUq/DCTR2l+IzcYJWN319Dm/R0dHBiBEjAGhrayM7O9vjiIKL3SWIz0QJWt30V0dfpeDoUWhqguZmuHDRLruri7RB+mAk+/nnIS0NrPOkvDzIz4eiIoixB1QosPbj/XzaXUI/n3aXID7t9K+bMMBnr0sY6NMnLr1r4ZuaoKZGf3/zTairg/p6LSo/X8saM0YvHzIE0tP190gEzp6Flhb9u7lZr6u1FYqLoawMZs7Uy2bN0usKA5ZPu0sY6NPuEqJ92l1CtM8wuoQvrpsw0KflEgb69EndNJvwjY2wZQtUVuq95fXX6/k33ADXXAMlJRDvIVFHBxw8CO+8A7t26Xm7d0NhIdxyCyxaBGPHOrARPsFyCdE+7S4hPp8dHXpq92l3CcnrM8nrpvsJX1Wlp889B2+/DYsXw7x5UF7u/mGOUlpwZSVs3gzTp8N99+llc+a4W7ZbVFVFuwQzPu0uIdpnkF1CqOpmIK7SC4LgEMotqquVmjZNqUmT9GfTJqUiEdeK+1IiER2DFc+0aTrGoGD36bVLpaJ9BtmlH3warJvOJ/zf/65URYVS48crtW2b46t3jG3bdIwVFTpmP2K59LtPu8sg+PSzS6VcrZvOHtLv2AGlpTBpkr6quWCBo6t3lAULdIyTJumYd+zwOqJo7C797tPuMgg+/ewS3K2bjuw2VqzQn3HjlKqrc2SVRqmr07GvWOF1JJogu1RKfDqJ3aUDPhO7Sq8UPPUUrFypf3/+OeTkOLQrMszJk3DjjXqPCrBxo/kY7D6D7BKifXrpEoLv03IJCftMrKfdPfdAbS10durfmZkJrc5Thg3Tt0mysvTvIUNg3TqzMdh9BtklRPv00iUE36flEhL2KbflBCFExJ/wa9fC3r26w0JmZrD3oBaZmXD6tP7s2aO30QRr1w70mQxYPi2XJn1aLpPFp5VjidbNuM786+uVGjVKqSNHEr6I4FsaGpTKzdXb6iaWy2T2abk06TNZXSqVUN2M76LdTTfpPsDLlsW3lwkKGzbAK69AdbV7ZVguIbl9btigp6Z8JrNLiL9uXvIuYudOpYqLlTp//pL/NBFOnDhhtDyllN7G4mK9zW5gd2nQZ0tLizp37pw6d+6csTJ7t9GUTw84f/68On78uDp+/LiJwuJyeenn8C++CEuXwiD3r/d9+OGHfPjhh5SXl5Ofn09xcTE7THboGDRItxQvvODO+u0uDfhsampi/vz5zJs3j4KCAgoKCvjTn/7kerlA3zaa8mmIZ555hpSUFFJSUhg8eDAnTpzgxIkT7hccp8vYD+kjET0dPVo/52vdvnIRa7jfH/7wh1xxxRUsX76cnTt38sknnzDI1D+1s1M///zZZ9HPkSdKJGLUJcDLL7/M3LlzSU9P56GHHgLgzTffpMZ69tsESeTz/Pnz3HffffzoRz8C9Ki1RdbgISawu4SYfMptOUEIEbEn/P79+jN+vJE96Geffcadd97JnXfeybRp08jJyeHBBx/k2LFjfPDBB66X30tWlt7m/fudXa9Blxbf+c53SL/QCkydOpWpU6cybtw4Y+UDSeXzj3/8I59++il/+9vf+OY3v2m2dYdolzH6jL2nnTVkUr9xzd1i9OjRjB49OmpeQUEBY8aM4aqrrjISQy9lZXr7p093bp319cZcWmRdSIYzZ87w6quvAnjz0sMk8blv3z6qq6v5/e9/z9VXX83WrVu58sorjcbQ6xJi8hl7C9/Wpj8e9kfevXs3t9xyi7nzd4ucHL3tTuKRy7/+9a9MnjyZl156iZdeeonf/va3xmNIFp+rVq3ixIkTvPrqqxw7dozbbruN8+fPc/78eXNBWC5j9OmvUWv/BUopfvOb37DOdJ/sJONb3/oW7777Lr/85S8B/erje+65p7f1Fy6NwYMHM3fuXGpra5kwYQLvv/8+AFdffbXHkV2c2JvKESP0p73dxXC+mGeffZb7778/akx1Y7S36213Eg9dZmRk8Oijj/Loo4+Sm5vLa6+9ZjaAJPMJcPnll3P11VfT0tJCizWisgkslzH6jD3hi4v1p64u3tDi5vXXX+fyyy+n9MKjq/aXIRqhrk5vu5N45LI/48aNo6CgwGyhSerz7NmzTJw4kYkTJ5or1HIZo8/YE37KFP05cqTvcViXOXToEIcOHWLXrl1ceeWVNDQ08N577/Hss88aKR/Q23rkiN52JzHsEnRHJouOjg46OjrIzMwc8IJJV0kCn2fPnuXs2bPUWo/fAocPH2by5MkUFRWZu1pvdxmjT7kPLwghIvaLdlYvnptvhk2b9AADLvLPf/6Tm2++GYCPP/6YX/ziF73Lnn/+eVfLjmLTJr3NTvYKA70+Qy4Benp6mD9/Pqmpqdx66610d3cDsGnTJtfLjiIJfHZeOIq47bbbGDlyJPPnz6e7u5uNpkf2icflJXfa9/gBBaMk4cMz7e3tRsoZQBI+PNPV1aUaGxvNPoRkYezhmdmz9Tu1fvWrS/7TwLFxo+6rPHu2O+u3uzTkc9iwYUbKGcDGjWZ9GmDo0KF8/etf57LLLjNSXhTxuoxr71Jfrx/Ab2iI688DQUODHkjh4EF3y7FcJrNPy6VJn8nqUqmE6mb8o9auXQtbt+q3bDp9PuYlXV16OnMmLFwIy5e7X6Y1XFGy+rRcgjmflktIXp9xuIy/p93y5dDQABkZyTFqLcCpUzBjhv4+a5aZygl95dh9Bt0l9Pk06RKi6yYkh89Tp/Q0QZ9yW04QQkTir4u+6y44cEB/r67WY2gHkfZ2GD4cnn5a/37gAfdfGXwxLJ9BdgnRPr10CcH3abmExH06chFBXjXlLEF2qZT4dBKHXzXl7NtjX35ZXz38+c+V6u52dNWu0N2tYx01SsfuJ+wug+DTchkEn353qZRrddPZc/iKCti3Tx9ClZTA9u2Ort5Rtm/XMR44oGOuqPA6omjsLv3u0+4yCD797BLcrZuO7Tr6U12tX2xvveT+17/WL773ikhEx2DFM22ajjEo2H167VKpaJ9BdukHnwbrZuIX7b6Mqio9XbdOv9xv8WKYNw/Ky92/kKMUvPGGHrB/82Z9S+Pee/WyOXPcLdstqqqiXYIZn3aXEO0zyC4hVHVTbssJQohwv4W309gIW7ZAZSUcPQrXXafnl5frwfhKSuK/ddLRoc956ur0nhPgrbegqAjmz4dFi2DsWCe2wh9YLiHap90lxOezo0NP7T7tLiF5fSZ53TSb8Haam/u6PtbU6IsT9fUwcqR+KCAvTz8IAZCaCmlp+jArEoEzZ8AaRqi5WX9aW/U/pbRU90QC3QUxP9/8tnmB5dPuEgb6tLuEaJ92lxDtM4wu4YvrJgz0abmEgT59Uje9S/iLoRR88gk0NUVXvEhE9yFWSveLTk+H3Fy9LC9Piyss9KZzh1+x/q39fUYi/G7vXqx/++3f/nafT7tLEJ92+tdN6PU5oG7CQJ8+cemvhBeM8Nhjj9HT09P7XQgPctFOEEJEYMalF5wjJSXF/Ms8BF8g/3VBCBHSwocQpVTvObwQLqSFF4QQIS18CBk0aBBycyacSMKHkJ6eHkn4kCKH9IIQIiThBSFESMILQoiQhBeEECEJLwghQq7ShxC5LRdeJOFDiNyWCy9ySC8IIUISXhBChCS8IIQISXhBCBGS8IIQIiThBSFEyG25ECL34cOLJHwIkfvw4UUO6QUhREjCC0KIkIQXhBAhCS8IIUISXhBChFylDwnr16+ntrYWgMOHD/depT9y5AgAM2bMYOnSpQweLFUimZGXSYaElBjeXipVIfmRQ/qQsHr1atLS0i66LC0tjVWrVhmOSPACaeFDQmNjIxMmTKC7u3vAsqFDh3L48GEKrffCC0mLtPAhYezYsUyYMOGiy8aPHy/JHhIk4QUhREjCh4i7776bjIyMqHkZGRksWbLEo4gE08g5fIhobW2loKCAM2fO9M5LTU3l2LFj5ObmehiZYApp4UNEbm4uZWVlUfNKS0sl2UOEJHzIWLJkCVlZWb2fpUuXeh2SYBA5pA8ZHR0djBgxovd3W1sb2dnZHkYkmET6USYr1n786FFoaoLmZmhtJburi7RBfQd22c8/D2lpkJsLeXmQnw9FRXphDL3zhGAhh/SCECLkkD5ZaGqCmhp4802oq4P6ej0/N1e32nl5MGYMDBkC6el9fxeJwNmz0NKijwKamqC1VS8rLoayMpg5E2bN0usRAo0kfFBpbIQtW/T3ykp96H799XDDDXDNNVBSopfFc37e0aGnBw/CO+/Arl2wezcUFsItt+hlixbB2LEJboRgGkn4oFFVBc89B2+/DYsX63nz5kF5ubvn3ErpxK+s1L83b4bp0+G++2DOHPfKFRxFEj4o7NwJDz+sD8F//GO49VZ9sc0rurrg//4P1qzRpwirVsFNN3kXjxATkvB+5tgx+M//1N/ffx9Wr4YFC7yN6WJs3w4PPQSTJ+vf//M/UFDgbUzCRZGr9H5lxw4oLYVJk/Snvt6fyQ46rvr6vlhLS3X8gu+QhBeEECGH9H5k5UrYtk2fI5eWeh3NpbNvn77G8O//Dk884XU0gg1JeD+hFDz1lE74zz+HnByvI4qfkyfhxhv1DmvjRq+jES4gXWv9xD33QG0tdHZCZqbX0STGsGH6Nl5Wlu7ss26d1xEJSML7g7Vr9XTvXn1/3cvbbU6SmQmnT+teetY2Ll/ubUwhRw7pvebQId1pBuCtt+Dyy72Nxw0++kh30gHd6k+c6Gk4YUYS3mtuuqmvu+qyZd7G4iYbNujpK69AdbW3sYQYuS0nCCFCWngvee013ZPu/ff170Hm97/Hjx/n9OnTFFnPwLtFT4+eTp6se+LNnu1uecJFkRbeS158EZYu1YluMNmrqqq44447uOOOO/jggw8oMNEN1trGZcvghRfcL0+4KNLCe0UkAqNH62fQs7KMFfvkk0/y5z//mddffx2AIUOGGCsb0Lcc8/Lgs8+in8sXjCC35bxi/34YP95osu/du5fHH3+cQ4cOmU90i6wsvd379/dduReMIQnvFfX1ejQZg/zkJz9hxowZ1NTU8NJLLwEwd+7cAUNXu05Zmd5+SXjjyDm8V7S1Ge0629PTw759+zh37hxf+9rXyM7OJjs7m+nTp/Puu+8aiwPQ293WZrZMAZAWPjR8/PHHdHZ2smbNGsrKyphzYZSampoatm/fztSpUz2OUDCBtPCCECIk4b1ixAhobzdW3PDhwwFI69dP/5prruEvf/mLsTgAvd22l2EI5pCE94riYj2ctCG++tWvkpeXx3vvvRc1PzMzk6985SvG4gD0dhcXmy1TACThvWPKFDhyRN+XNsRPf/pTdu3aFTVv3759fP/73zcWA52derunTDFXptCLdLzxkoULYcYM/Ry8AXp6enjwwQcZNWoUbReukp8+fZo1a9Zw2WWXGYmB9ev1M/9bt5opT4hCEt5LPOpLf+rUKax/e5apjj/Sl94XSMJ7jTweKxhEzuEFIURIC+81hw7p98GBHt5q3DhPw3GFjz7S1yoAXn9drtB7iCS8H7DGe9u6Vb8BNpmeIuvq0m+fXbhQ/5Yx7TxFutb6ASsJGhogIyM5Rq0FOHVKt+yzZkmi+wRp4f3GXXfBgQP6wtawYV5HEz/t7TB8ODz9NDzwgLtvthViRi7a+Y3//V/4t3+DqVP1G1yCyL59+gUUK1bAf/2XJLuPkBber+zYAf/xH/oDOnlSU72N6V9x5gw8+aT+vmGD/lRUeBuTMABp4QUhREjC+5WKCn1ofOCA/pSU6Pew+5Ht23V8Vqz79knr7lPkkD4o7NwJDz+sB7+8/3647TZvX0nV1QW/+x3893/r24irVuleg4KvkYQPGlVV+sWMtbWweLGeN2+efl2VmxfHlII33tBdYwE2b9a33O69Fy6MniP4H0n4oNLYCFu26O+VlXD0KFx3nU78sjJ9iA3x3drr6NDTAwf0s+tvvKHfe1dUBPPn62WLFsHYsYluhWAYSfhkoblZ99KrqdHn0PX1ev7IkXoc+Lw8GDNGX+lPS+s7GohE9BX2lha9juZmaG3Vy0pK9O21WbN0b7n8fG+2TXAMSfhkxfq3fvIJNDX1JXIkos+/reXp6fqTm6t3Cvn5UFiol8n986RDrtILQoiQFl4QQoS08IIQIiThBSFESMILQoiQhBeEECEJLwghQhJeEEKEJLwghAhJeEEIEZLwghAi/h/+PXEmxckDbwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%pylab inline\n",
    "%load_ext memory_profiler\n",
    "from pomegranate import BayesianNetwork\n",
    "import seaborn, time\n",
    "seaborn.set_style('whitegrid')\n",
    "\n",
    "X = numpy.random.randint(2, size=(2000, 7))\n",
    "X[:,3] = X[:,1]\n",
    "X[:,6] = X[:,1]\n",
    "\n",
    "X[:,0] = X[:,2]\n",
    "\n",
    "X[:,4] = X[:,5]\n",
    "\n",
    "model = BayesianNetwork.from_samples(X, algorithm='exact')\n",
    "print(model.structure)\n",
    "model.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The structure attribute returns a tuple of tuples, where each inner tuple corresponds to that node in the graph (and the column of data learned on). The numbers in that inner tuple correspond to the parents of that node. The results from this structure are that node 3 has node 1 as a parent, that node 2 has node 0 as a parent, and so forth. It seems to faithfully recapture the underlying dependencies in the data.\n",
    "\n",
    "Now, two algorithms for performing search-and-score were mentioned, the traditional shortest path algorithm and the A\\* algorithm. These both work by essentially turning the Bayesian network structure learning problem into a shortest path problem over an 'order graph.' This order graph is a lattice made up of layers of variable sets from the BNSL problem, with the root node having no variables, the leaf node having all variables, and layer `i` in the lattice having all subsets of variables of size `i`. Each path from the root to the leaf represents a certain topological sort of the variables, with the shortest path corresponding to the optimal topological sort and Bayesian network. Details can be found <a href=\"http://url.cs.qc.cuny.edu/publications/Yuan11learning.pdf\">here</a>. The traditional shortest path algorithm calculates the values of all edges in the order lattice before finding the shortest path, while the A\\* algorithm searches only a subset of the order lattice and begins searching immediately. Both methods yield optimal Bayesian networks.\n",
    "\n",
    "A major problem that arises in the traditional shortest path algorithm is that the size of the order graph grows exponentially with the number of variables, and can make tasks infeasible that have otherwise-reasonable computational times. While the A\\* algorithm is faster computationally, another advantage is that it uses a much smaller amount of memory since it doesn't explore the full order graph, and so can be applied to larger problems.\n",
    "\n",
    "In order to see the differences between these algorithms in practice, let's turn to the task of learning a Bayesian network over the digits dataset. The digits dataset is comprised of over a thousand 8x8 pictures of handwritten digits. We binarize the values into 'on' or 'off' for simplicity, and try to learn dependencies between the pixels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x288 with 3 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from sklearn.datasets import load_digits\n",
    "\n",
    "X, y = load_digits(10, True)\n",
    "X = X > numpy.mean(X)\n",
    "\n",
    "plt.figure(figsize=(14, 4))\n",
    "plt.subplot(131)\n",
    "plt.imshow(X[0].reshape(8, 8), interpolation='nearest')\n",
    "plt.grid(False)\n",
    "plt.subplot(132)\n",
    "plt.imshow(X[1].reshape(8, 8), interpolation='nearest')\n",
    "plt.grid(False)\n",
    "plt.subplot(133)\n",
    "plt.imshow(X[2].reshape(8, 8), interpolation='nearest')\n",
    "plt.grid(False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Shortest Path\n",
      "Time (s):  42.78771615028381\n",
      "P(D|M):  -8267.950447476833\n",
      "peak memory: 2234.61 MiB, increment: 1932.45 MiB\n",
      "\n",
      "A* Search\n",
      "Time (s):  25.080483198165894\n",
      "P(D|M):  -8267.950447476833\n",
      "peak memory: 860.71 MiB, increment: 552.22 MiB\n"
     ]
    }
   ],
   "source": [
    "X = X[:,:18]\n",
    "    \n",
    "tic = time.time()\n",
    "model = BayesianNetwork.from_samples(X, algorithm='exact-dp') # << BNSL done here!\n",
    "t1 = time.time() - tic\n",
    "p1 = model.log_probability(X).sum()\n",
    "\n",
    "tic = time.time()\n",
    "model = BayesianNetwork.from_samples(X, algorithm='exact')\n",
    "t2 = time.time() - tic\n",
    "p2 = model.log_probability(X).sum()\n",
    "\n",
    "\n",
    "print(\"Shortest Path\")\n",
    "print(\"Time (s): \", t1)\n",
    "print(\"P(D|M): \", p1)\n",
    "%memit BayesianNetwork.from_samples(X, algorithm='exact-dp')\n",
    "print()\n",
    "print(\"A* Search\")\n",
    "print(\"Time (s): \", t2)\n",
    "print(\"P(D|M): \", p2)\n",
    "%memit BayesianNetwork.from_samples(X, algorithm='exact')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These results show that the A\\* algorithm is both computationally faster and requires far less memory than the traditional algorithm, making it a better default for the 'exact' algorithm. The amount of memory used by the BNSL process is under 'increment', not 'peak memory', as 'peak memory' returns the total memory used by everything, while increment shows the difference in peak memory before and after the function has run. \n",
    "\n",
    "#### Approximate Learning: Greedy Search (pomegranate default)\n",
    "\n",
    "A natural heuristic when a non-greedy algorithm is too slow is to consider the greedy version. This simple implementation iteratively finds the best variable to add to the growing topological sort, allowing the new variable to draw only from variables already in the topological sort. This is the default in pomegranate because it has a nice balance between producing good (often optimal) graphs and having a small computational cost and memory footprint. However, there is no guarantee that this produces the globally optimal graph.\n",
    "\n",
    "Let's see how it performs on the same dataset as above."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Greedy\n",
      "Time (s):  1.4977431297302246\n",
      "P(D|M):  -8434.745069065655\n",
      "peak memory: 216.68 MiB, increment: 0.07 MiB\n"
     ]
    }
   ],
   "source": [
    "tic = time.time()\n",
    "model = BayesianNetwork.from_samples(X) # << Default BNSL setting\n",
    "t = time.time() - tic\n",
    "p = model.log_probability(X).sum()\n",
    "\n",
    "print(\"Greedy\")\n",
    "print(\"Time (s): \", t)\n",
    "print(\"P(D|M): \", p)\n",
    "%memit BayesianNetwork.from_samples(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Approximate Learning: Chow-Liu Trees\n",
    "\n",
    "However, there are even cases where the greedy heuristic is too slow, for example hundreds of variables. One of the first heuristics for BNSL is that of Chow-Liu trees, which learns the optimal tree from data. Essentially it calculates the mutual information between all pairs of variables and then finds the maximum spanning tree. A root node has to be input to turn the undirected edges based on mutual information into directed edges for the Bayesian network. The algorithm is is $O(d^{2})$ and practically is extremely fast and memory efficient, though it produces structures with a worse $P(D|M)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Chow-Liu\n",
      "Time (s):  0.045445919036865234\n",
      "P(D|M):  -8752.32666094451\n",
      "peak memory: 190.02 MiB, increment: 0.00 MiB\n"
     ]
    }
   ],
   "source": [
    "tic = time.time()\n",
    "model = BayesianNetwork.from_samples(X, algorithm='chow-liu') # << Default BNSL setting\n",
    "t = time.time() - tic\n",
    "p = model.log_probability(X).sum()\n",
    "\n",
    "print(\"Chow-Liu\")\n",
    "print(\"Time (s): \", t)\n",
    "print(\"P(D|M): \", p)\n",
    "%memit BayesianNetwork.from_samples(X, algorithm='chow-liu')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Comparison\n",
    "\n",
    "We can then compare the algorithms directly to each other on the digits dataset as we expand the number of pixels to consider."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "X, _ = load_digits(10, True)\n",
    "X = X > numpy.mean(X)\n",
    "\n",
    "t1, t2, t3, t4 = [], [], [], []\n",
    "p1, p2, p3, p4 = [], [], [], []\n",
    "n_vars = range(8, 19)\n",
    "\n",
    "for i in n_vars:\n",
    "    X_ = X[:,:i]\n",
    "\n",
    "    tic = time.time()\n",
    "    model = BayesianNetwork.from_samples(X_, algorithm='exact-dp') # << BNSL done here!\n",
    "    t1.append(time.time() - tic)\n",
    "    p1.append(model.log_probability(X_).sum())\n",
    "\n",
    "    tic = time.time()\n",
    "    model = BayesianNetwork.from_samples(X_, algorithm='exact')\n",
    "    t2.append(time.time() - tic)\n",
    "    p2.append(model.log_probability(X_).sum())\n",
    "\n",
    "    tic = time.time()\n",
    "    model = BayesianNetwork.from_samples(X_, algorithm='greedy')\n",
    "    t3.append(time.time() - tic)\n",
    "    p3.append(model.log_probability(X_).sum())\n",
    "\n",
    "    tic = time.time()\n",
    "    model = BayesianNetwork.from_samples(X_, algorithm='chow-liu')\n",
    "    t4.append(time.time() - tic)\n",
    "    p4.append(model.log_probability(X_).sum())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x1113a65d0>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1008x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(14, 4))\n",
    "plt.subplot(121)\n",
    "plt.title(\"Time to Learn Structure\", fontsize=14)\n",
    "plt.xticks(fontsize=14)\n",
    "plt.yticks(fontsize=14)\n",
    "plt.ylabel(\"Time (s)\", fontsize=14)\n",
    "plt.xlabel(\"Variables\", fontsize=14)\n",
    "plt.plot(n_vars, t1, c='c', label=\"Exact Shortest\")\n",
    "plt.plot(n_vars, t2, c='m', label=\"Exact A*\")\n",
    "plt.plot(n_vars, t3, c='g', label=\"Greedy\")\n",
    "plt.plot(n_vars, t4, c='r', label=\"Chow-Liu\")\n",
    "plt.legend(fontsize=14, loc=2)\n",
    "\n",
    "plt.subplot(122)\n",
    "plt.title(\"$P(D|M)$ with Resulting Model\", fontsize=14)\n",
    "plt.xlabel(\"Variables\", fontsize=14)\n",
    "plt.ylabel(\"logp\", fontsize=14)\n",
    "plt.plot(n_vars, p1, c='c', label=\"Exact Shortest\")\n",
    "plt.plot(n_vars, p2, c='m', label=\"Exact A*\")\n",
    "plt.plot(n_vars, p3, c='g', label=\"Greedy\")\n",
    "plt.plot(n_vars, p4, c='r', label=\"Chow-Liu\")\n",
    "plt.legend(fontsize=14)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see the expected results-- that the A\\* algorithm works faster than the shortest path, the greedy one faster than that, and Chow-Liu the fastest. The purple and cyan lines superimpose on the right plot as they produce graphs with the same score, followed closely by the greedy algorithm and then Chow-Liu performing the worst."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Constraint Graphs\n",
    "\n",
    "Now, sometimes you have prior information about how groups of nodes are connected to each other and want to exploit that. This can take the form of a global ordering, where variables can be ordered in such a manner that edges only go from left to right, for example. However, sometimes you have layers in your network where variables are a part of these layers and can only have parents in another layer.\n",
    "\n",
    "Lets consider a diagnostics Bayesian network like the following (no need to read code, the picture is all that is important for now):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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bwZg+PDh0Qwsyezfvx+AxYsXAzBx4sQIRyMiIiLxQpkNEREREREJhDIbkitUrFgRgGXLlgHQrFkzAG699VYAJkyYAPiVUSRzli9fDkC1atUAKF26dJTDERERkTihf1mJiIiIiEgglNmQXKVkyZIALFq0CPA7i3fo0AHw7xoULFgwgtElLuuvYVW/RERERECZDRERERERCYgyG5IrHX300QC88847AHTs2BGA5s2bA/D6668DUKxYsQhGl3isv8ajjz4a8UhEREQkniizISIiIiIigchzUG07RVK613br1g2AFStWADB79mwAypYtG83A4oRlLCwTdMMNNwBw4YUXAnDxxRcDfof2AgUKhD1EEYlj48aNA/yKgOarr74C/DW4evXqMe+vW7cuAF27dgUgXz4dyBBJNMpsiIiIiIhIIJTZEDmE/v37AzBt2jQAFixYkPK+E044IZIxRalFixYAvP3224B/5+XAgQMAFCpUKObjrMrXFVdcAUDhwoXDG6yIxJ08efJk6/P1TxWRxKXMhoiIiIiIBEKHH0UOYdCgQYB/V+Oiiy5Ked+cOXMAOO2008IfWESOP/74mL//8ccfMX/fs2cPAJMmTQLgjTfeAGDnzp0A/PLLLwCUK1cu0HGKSHwaMmQIAI888gjgrxnpsWxpv379gh2YiAROmQ0REREREQmE/rMhIiIiIiKB0DEqkcO48847AShTpkzK2y655BIA3nrrLQDOP//80McVtuOOOy5TH28Xx+3IhI5PieRuHTp0APwjqkdiF8Lt80QkcSmzISIiIiIigVBmQyQDrIkdwDHHHAP4ZV2nTp0KQOPGjWM+Z9++fYBfDtYaBrZq1SrYwQagdOnSABQsWBCAvXv3HvLjjjrK7V+ccsopAPTt2zeE0YlIvKtUqRIA1apVA2DlypWH/fiqVasCULly5WAHJiKBU2ZDREREREQCocyGSCY1b94cgNdffx2Ali1bAvDEE08AcNVVVwF+uVzbwVu3bl3Mx2e3yVWYSpUqBUCBAgWA9DMblvmYOXMm4Gc6REQAbr/9dgAeeOAB4O9ltK1haJcuXcIdmIgERv8SEBERERGRQOQ5aCUfRCRLLHNx2WWXAXD66acDsHz5cgB2794NQNGiRQF47rnnALj22mtDHWd2zJ49G4Drr78egN9++y3m/UWKFAHgscceA6Br164hjk5E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\n",
      "text/plain": [
       "<Figure size 1008x720 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pomegranate import DiscreteDistribution, ConditionalProbabilityTable, Node\n",
    "\n",
    "BRCA1 = DiscreteDistribution({0: 0.999, 1: 0.001})\n",
    "BRCA2 = DiscreteDistribution({0: 0.985, 1: 0.015})\n",
    "LCT   = DiscreteDistribution({0: 0.950, 1: 0.050})\n",
    "\n",
    "OC = ConditionalProbabilityTable([[0, 0, 0, 0.999],\n",
    "                                  [0, 0, 1, 0.001],\n",
    "                                  [0, 1, 0, 0.750],\n",
    "                                  [0, 1, 1, 0.250],\n",
    "                                  [1, 0, 0, 0.700],\n",
    "                                  [1, 0, 1, 0.300],\n",
    "                                  [1, 1, 0, 0.050],\n",
    "                                  [1, 1, 1, 0.950]], [BRCA1, BRCA2])\n",
    "\n",
    "LI = ConditionalProbabilityTable([[0, 0, 0.99],\n",
    "                                  [0, 1, 0.01],\n",
    "                                  [1, 0, 0.20],\n",
    "                                  [1, 1, 0.80]], [LCT])\n",
    "\n",
    "PREG = DiscreteDistribution({0: 0.90, 1: 0.10})\n",
    "\n",
    "LE = ConditionalProbabilityTable([[0, 0, 0.99],\n",
    "                                  [0, 1, 0.01],\n",
    "                                  [1, 0, 0.25],\n",
    "                                  [1, 1, 0.75]], [OC])\n",
    "\n",
    "BLOAT = ConditionalProbabilityTable([[0, 0, 0, 0.85],\n",
    "                                     [0, 0, 1, 0.15],\n",
    "                                     [0, 1, 0, 0.70],\n",
    "                                     [0, 1, 1, 0.30],\n",
    "                                     [1, 0, 0, 0.40],\n",
    "                                     [1, 0, 1, 0.60],\n",
    "                                     [1, 1, 0, 0.10],\n",
    "                                     [1, 1, 1, 0.90]], [OC, LI])\n",
    "\n",
    "LOA = ConditionalProbabilityTable([[0, 0, 0, 0.99],\n",
    "                                   [0, 0, 1, 0.01],\n",
    "                                   [0, 1, 0, 0.30],\n",
    "                                   [0, 1, 1, 0.70],\n",
    "                                   [1, 0, 0, 0.95],\n",
    "                                   [1, 0, 1, 0.05],\n",
    "                                   [1, 1, 0, 0.95],\n",
    "                                   [1, 1, 1, 0.05]], [PREG, OC])\n",
    "\n",
    "VOM = ConditionalProbabilityTable([[0, 0, 0, 0, 0.99],\n",
    "                                   [0, 0, 0, 1, 0.01],\n",
    "                                   [0, 0, 1, 0, 0.80],\n",
    "                                   [0, 0, 1, 1, 0.20],\n",
    "                                   [0, 1, 0, 0, 0.40],\n",
    "                                   [0, 1, 0, 1, 0.60],\n",
    "                                   [0, 1, 1, 0, 0.30],\n",
    "                                   [0, 1, 1, 1, 0.70],\n",
    "                                   [1, 0, 0, 0, 0.30],\n",
    "                                   [1, 0, 0, 1, 0.70],\n",
    "                                   [1, 0, 1, 0, 0.20],\n",
    "                                   [1, 0, 1, 1, 0.80],\n",
    "                                   [1, 1, 0, 0, 0.05],\n",
    "                                   [1, 1, 0, 1, 0.95],\n",
    "                                   [1, 1, 1, 0, 0.01],\n",
    "                                   [1, 1, 1, 1, 0.99]], [PREG, OC, LI])\n",
    "\n",
    "AC = ConditionalProbabilityTable([[0, 0, 0, 0.95],\n",
    "                                  [0, 0, 1, 0.05],\n",
    "                                  [0, 1, 0, 0.01],\n",
    "                                  [0, 1, 1, 0.99],\n",
    "                                  [1, 0, 0, 0.40],\n",
    "                                  [1, 0, 1, 0.60],\n",
    "                                  [1, 1, 0, 0.20],\n",
    "                                  [1, 1, 1, 0.80]], [PREG, LI])\n",
    "\n",
    "s1 = Node(BRCA1, name=\"BRCA1\")\n",
    "s2 = Node(BRCA2, name=\"BRCA2\")\n",
    "s3 = Node(LCT, name=\"LCT\")\n",
    "s4 = Node(OC, name=\"OC\")\n",
    "s5 = Node(LI, name=\"LI\")\n",
    "s6 = Node(PREG, name=\"PREG\")\n",
    "s7 = Node(LE, name=\"LE\")\n",
    "s8 = Node(BLOAT, name=\"BLOAT\")\n",
    "s9 = Node(LOA, name=\"LOA\")\n",
    "s10 = Node(VOM, name=\"VOM\")\n",
    "s11 = Node(AC, name=\"AC\")\n",
    "\n",
    "model = BayesianNetwork(\"Hut\")\n",
    "model.add_nodes(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11)\n",
    "model.add_edge(s1, s4)\n",
    "model.add_edge(s2, s4)\n",
    "model.add_edge(s3, s5)\n",
    "model.add_edge(s4, s7)\n",
    "model.add_edge(s4, s8)\n",
    "model.add_edge(s4, s9)\n",
    "model.add_edge(s4, s10)\n",
    "model.add_edge(s5, s8)\n",
    "model.add_edge(s5, s10)\n",
    "model.add_edge(s5, s11)\n",
    "model.add_edge(s6, s9)\n",
    "model.add_edge(s6, s10)\n",
    "model.add_edge(s6, s11)\n",
    "model.bake()\n",
    "\n",
    "plt.figure(figsize=(14, 10))\n",
    "model.plot()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This network contains three layer, with symptoms on the bottom (low energy, bloating, loss of appetite, vomitting, and abdominal cramps), diseases in the middle (overian cancer, lactose intolerance, and pregnancy), and genetic tests on the top for three different genetic mutations. The edges in this graph are constrainted such that symptoms are explained by diseases, and diseases can be partially explained by genetic mutations. There are no edges from diseases to genetic conditions, and no edges from genetic conditions to symptoms. If we were going to design a more efficient search algorithm, we would want to exploit this fact to drastically reduce the search space of graphs.\n",
    "\n",
    "Before presenting a solution, lets also consider another situation. In some cases you can define a global ordering of the variables, meaning you can order them from left to right and ensure that edges only go from the left to the right. This can represent some temporal separation (things on the left happen before things on the right), physical separation, or anything else. This would also dramatically reduce the search space. \n",
    "\n",
    "In addition to reducing the search space, an efficient algorithm can exploit this layered structure. A key property of most scoring functions is the idea of \"global parameter independence\", meaning that that the parents of node A are independent of the parents of node B assuming that they do not form a cycle in the graph. If you have a layered structure, either like in the diagnostics network or through a global ordering, it is impossible to form a cycle in the graph through any valid assignment of parent values. This means that the parents for each node can be identified independently, drastically reducing the runtime of the algorithm.\n",
    "\n",
    "Now, sometimes we know ~some things~ about the structure of the variables, but nothing about the others. For example, we might have a partial ordering on some variables but not know anything about the others. We could enforce an arbitrary ordering on the others, but this may not be well justified. In essence, we'd like to exploit whatever information we have.\n",
    "\n",
    "Abstractly, we can think about this in terms of constraint graphs. Lets say you have some symptoms, diseases, and genetic tests, and don't a priori know the connection between all of these pieces, but you do know the previous layer structure. You can define a \"constraint graph\" which is made up of three nodes, \"symptoms\", \"diseases\", and \"genetic mutations\". There is a directed edge from genetic mutations to diseases, and a directed edge from diseases to symptoms. This specifies that genetic mutations can be parents to diseases, and diseases to symptoms. It would look like the following:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import networkx\n",
    "from pomegranate.utils import plot_networkx\n",
    "\n",
    "constraints = networkx.DiGraph()\n",
    "constraints.add_edge('genetic conditions', 'diseases')\n",
    "constraints.add_edge('diseases', 'symptoms')\n",
    "plot_networkx(constraints)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All variables corresponding to these categories would be put in their appropriate name. This would define a scaffold for structure learning.\n",
    "\n",
    "Now, we can do the same thing for a global ordering. Lets say we have 3 variables in an order from 0-2. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "constraints = networkx.DiGraph()\n",
    "constraints.add_edge(0, 1)\n",
    "constraints.add_edge(1, 2)\n",
    "constraints.add_edge(0, 2)\n",
    "plot_networkx(constraints)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this graph, we're saying that variable 0 can be a parent for 1 or 2, and that variable 1 can be a parent for variable 2. In the same way that putting multiple variables in a node of the constraint graph allowed us to define layers, putting a single variable in the nodes of a constraint graph can allow us to define an ordering.\n",
    "\n",
    "To be specific, lets say we want to find the parents of the variables in node 1 given that those variables parents can only come from the variables in node 0. We can independently find the best parents for each variable in node 1 from the set of those in node 0. This is significantly faster than trying to find the best Bayesian network of all variables in nodes 0 and 1. We can also do the same thing for the variables in node 2 by going through the variables in both nodes 0 and 1 to find the best parent set for the variables in node 2.\n",
    "\n",
    "However, there are some cases where we know nothing about the parent structure of some variables. This can be solved by including self-loops in the graph, where a node is its own parent. This means that we know nothing about the parent structure of the variables in that node and that the full exponential time algorithm will have to be run. The naive structure learning algorithm can be thought of as putting all variables in a single node in the constraint graph and putting a self-loop on that node. \n",
    "\n",
    "We are thus left with two procedures; one for solving edges which are self edges, and one for solving edges which are not. Even though we have to use the exponential time procedure on variables in nodes with self loops, it will still be significantly faster because we will be using less variables (except in the naive case).\n",
    "\n",
    "Frequently though we will have some information about some of the nodes of the graph even if we don't have information about all of the nodes. Lets take the case where we know some variables have no children but can have parents, and know nothing about the other variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "constraints = networkx.DiGraph()\n",
    "constraints.add_edge(0, 1)\n",
    "constraints.add_edge(0, 0)\n",
    "plot_networkx(constraints)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this situation we would have to run the exponential time algorithm on the variables in node 0 to find the optimal parents, and then run the independent parents algorithm on the variables in node 1 drawing only from the variables in node 0. To be specific:\n",
    "\n",
    "(1) Use exponential time procedure to find optimal structure amongst variables in node 0 \n",
    "(2) Use independent-parents procedure to find the best parents of variables in node 1, restricting the parents to be in node 0\n",
    "(3) Concatenate these parent sets together to get the optimal structure of the network given the constraints.\n",
    "\n",
    "We can generalize this to any arbitrary constraint graph:\n",
    "\n",
    "(1) Use exponential time procedure to find optimal structure amongst variables in nodes with self loops (including parents from other nodes if needed)\n",
    "(2) Use independent-parents procedure to find best parents of variables in a node given the constraint that the parents must come from variables in the node which is this nodes parent\n",
    "(3) Concatenate these parent sets together to get the optimal structure of the network given the constraints.\n",
    "\n",
    "According to the global parameter independence property of Bayesian networks, this procedure will give the globally optimal Bayesian network while exploring a significantly smaller part of the network.\n",
    "\n",
    "pomegranate supports constraint graphs in an extremely easy to use manner. Lets say that we have a graph with three layers like the diagnostic model, and five variables in each layer. We can define the constraint graph as a networkx DiGraph, with the nodes being tuples containing the column ids of each variable belonging to that variable.\n",
    "\n",
    "In this case, we're saying that (0, 1, 2, 3, 4) is the first node, (5, 6, 7, 8, 9) is the second node, and (10, 11, 12, 13, 14) is the final node. Lets make nodes 1, 7, and 12 related, 11, 13, 14 related, and 3 and 5 related. In this case, where should be an edge from 1 to 7, and 7 to 12. 11, 13, and 14 are all a part of the same layer and so that connection should be ignored, and then there should be a connection from 3 to 5."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Constraint Graph\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Learned Bayesian Network\n"
     ]
    },
    {
     "data": {
      "image/png": "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L6lNteW8WSwvl/76D7FX/vSnPyknJ0enn35683O5ubnKzc3Vxo0bPR1bkt2+8vJTf59oVh7n5Su3spISUltnnXWWRowY0fx9jx491L17d5133nmejispdFlJUuZf/5FsampScXGx5s2b5/mYko7sN27uhwnw+OOP6/HHH9dtt92WkPGahbC2fvzjH2vUqFFau3at5s6dq9LSUs/HlBTKrG688Ub98pe/1AsvvKBf/vKXuueee5r3TU+FLKu6ujpJUnV1dfNz0cboo48+8nRsSaFfO2zevFndunVr/j43N1d1dXXe/DI1ZLXlq5BnFf3lgyR9+umnyszMVGZmpq644gr3Bwvp2uFojY2N+v3vf6/vfOc73g4UZ1bOm8W9e6WcnLZMybHNmzera9eurZ7r2rWrunbtmpgFRU6O3c5TFc3K47x85VZWUkJq62jvvPOOJk6cqNREfJYtpFl98MEHGjJkiJ577jn99re/TciYzfuNm/uhxzZu3KhevXqpV69eys3N9Xy8VkJWW5FIRGVlZTp06JDOPvtsZWVlaeTIkXr//fc9HVdS6LKSpOuvv1733nuvpkyZovLycv3Lv/yL52NKCl1WgwYN0t/8zd+0WiekpKQoJSXFu9/OtxTytcPRa6+0tDSdccYZ2rRpk/uDhay2fJUkWT355JMaMmSIVq5cqZUrV3qzng/h2uFYFi5cmJh/5+PMKnFXfXCgsbFRaWlprZ7r2LGjOnbsmJhFPdoFY4z+67/+Sz//+c/9nkqgnX/++Xr//ff105/+VA888EDzb+9xRGNjo1asWKHrrrtO1113nd/TCby//OUvqqur08MPP6zx48fr7rvv1lVXXaVly5b5PbVA2r9/v3bu3Kmf/exneumllzR79my/pxRYt99+u37605/qt7/9rR599FGVlJSopKREBQUFfk8t8I619urQoYNOO+00n2aEZDJ16lRt27ZNAwYM0IABA7y/AFxIbdq0ST169Gh1lD8onHdgXbpINTUeTkXKz8/X7t27Wz1XV1enuro6DRgwwNOxJdnt69Ll1N8nmpXHefnKraykhNRWS4899pjuvvtudXFr/icT4qw6deqkn/3sZ8rNzdXq1au9HzC637i5H3po8eLFqqqq0qxZs5of7777rt56663E/DIiZLV1xhlnSFKroz0XXnihXn/9dU/HlRS6rCQ1X3Fx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\n",
      "text/plain": [
       "<Figure size 1152x576 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pomegranate time:  0.42864394187927246 ((), (), (), (), (), (3,), (), (1,), (), (), (), (), (7,), (), ())\n"
     ]
    }
   ],
   "source": [
    "numpy.random.seed(6)\n",
    "\n",
    "X = numpy.random.randint(2, size=(200, 15))\n",
    "\n",
    "X[:,1] = X[:,7]\n",
    "X[:,12] = 1 - X[:,7]\n",
    "\n",
    "X[:,5] = X[:,3]\n",
    "\n",
    "X[:,13] = X[:,11]\n",
    "X[:,14] = X[:,11]\n",
    "\n",
    "a = networkx.DiGraph()\n",
    "b = tuple((0, 1, 2, 3, 4))\n",
    "c = tuple((5, 6, 7, 8, 9))\n",
    "d = tuple((10, 11, 12, 13, 14))\n",
    "\n",
    "a.add_edge(b, c)\n",
    "a.add_edge(c, d)\n",
    "print(\"Constraint Graph\")\n",
    "plot_networkx(a)\n",
    "plt.show()\n",
    "\n",
    "print(\"Learned Bayesian Network\")\n",
    "\n",
    "tic = time.time()\n",
    "model = BayesianNetwork.from_samples(X, algorithm='exact', constraint_graph=a)\n",
    "\n",
    "plt.figure(figsize=(16, 8))\n",
    "model.plot()\n",
    "plt.show()\n",
    "print(\"pomegranate time: \", time.time() - tic, model.structure)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We see that reconstructed perfectly here. Lets see what would happen if we didn't use the exact algorithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA4sAAAD6CAYAAAAIhdKaAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8li6FKAAAgAElEQVR4nO3df7RVdZ3/8edFwAsIGHl1uBLQUtAA0QJTMVBKli5/rBTGH6U5tiZDDc0fTSU5k84XtdVYmBYRrdRp0BQltGE18WPUUMAQisHACJgU+ZEwEgh0+WH3fP/48Dk/OKBe7j17nx/Px1p37bP3xXs+533f7vv6nL3P3nWZTCaDJEmSJEl52qU9AEmSJElS+XGyKEmSJEkq4mRRkiRJklTEyaIkSZIkqYiTRUmSJElSESeLkiRJkqQiThYlSZIkSUWcLEqSJEmSijhZlCRJkiQVaZ/2AA4ok4HXXguP16+HDRtg82bYtStsa2oKy06dwrK+HhoaoLERjj02bOvbF+rqkhx1ZYq1Xr8+rOfXOtYZQq1jnSFXa+v8/mQyYRlrHesMhbW2p1vPnk5Ga3oarHVLvFtPQ2Gt6+vD4/z9R9++YZu1fm/5td6wIWx7r/2HPd1yLcl59nTr2NPJqOK5S10mE//ip2T9epg3Lzx+4QVYvBiWL88FuGOPDYXs2RM6dAjbYqFj4ffuhY0bwy8m/jHdvBkGDoShQ2H48LBtxIjcL6QWxVrHOkOu1rEu+bWOdYZQ61hnyNU61hlytbbOYZlf6+XLw7ZY61hnKKy1Pd0y+T0NhfsPe7rttHVPx5+Z39NgraHlPQ2Ftd67NzzO33/ESXz+/mPEiLCtVmt9oJ6GwlrHwPxe+w97+t21NufZ0+/fe+W81vQ0+DcxqrG5S/KTxbVrw/LRR2HGjDAL/8Qnwrazz4ZTT4VBg6Br19Y9z/bt8Pvfw8svw/PPh20vvgh9+sDo0XDllWFb796te55ytnZtrs6Qq3WsM7S+1rHOkKt1rDPkal3tdYbCnobCWg8aFLa1Ra3t6fA4f/9x9tlhW1vsP+zpIH//kURPQ2GtR48O26q91kn1NBTuP158MWzL339Uc53hvXsa2m7/Ues9DaXNefZ0YM5LRo3PXfzMoiRJkiSpSHJHFmfNggcegIULw/pVV8HFF8PIkcmdn5vJhJn6jBkwdWrYdsYZcNNNcO65yYyh1GbNCstY61hnSK7Wsc6Qq3WsM1RXrQ/W05Bsrau5p6Gw1lddFbYluf84WE9DddU61hkK9x9p9TQU7j+qpc5QHj0NhfsPe7o0arGnIfmcV0s9Dea8JKTd01AWOa+0k8U5c8LyjjvCObq33QaXXx62xQ8spyV+4PSJJ+A73wnnEk+YELaNGpXeuA7VnDm5OkOu1mnXGUKtY50hV+tKrTPY00mIPQ2FtU67zpDraSisdSXWGQr3H7fdFraVW61jnaFya21PJ8eeTka5/008UE9D5dbanFd65d7TkHzOy5TCG29kMmPGZDL9+oWvadNK8jRtatq03HjHjAmvody98UZhrSuhzplMrtaxzpVSa3s6Gfv3dCXVesyYyql1rHMl7T9iP9jTpWdPJ6MaerqSal1pfxPNecmxpw+q7SeLTz2VyRx9dCZz552ZzJ494atSxPHeeWd4DU89lfaIDi7WOb/WlSS/zpVS62rp6XKtdRxbpfd0Je0/4ngrtdb2dGnZ08mp5J6upFqb85JjzktGAj3tBW4kSZIkSUXa7jOL48eH5bRp4VzaIUPa5MemZsmScI7yZZeF9XvuSXc8+caPz9UZKrvWS5aEZax1udUZqq+noTxrPW1aeFxNtS63OkPh/qNa6gzlV2t7Ojn2dDKquaehPGttziutas15bdzTrZ8sZjLwrW/lCr51K3Tv3gZDKwNvvw2f+lR4PGQITJ6c3ljirynWuprqDLlap11nqP6ehvKo9YF6Gqqr1rHOkH6tv/Wt8Lja9h/l1NNQuP+wp0vHnk5OLfQ0pF9rc15yqj3ntXFPt2/1Txg3DhYsgB07wnqXLq3+kWWjW7fcpYGPOAI6dIAHH0xnLOPGhWWsdTXVGXK1jnWGdGtdzT0NhbW2p0sjv6ch/VovWBAeV1uty6mnoXD/UU11Bns6KQfqaUi/1tVWZzDnJcmcl4wS9HTrPrM4cSIsWhTuP9KlS3UVO4qv669/hZdeCq85abHO+bWuRvl1TrvW1dzTUNzTSde61nq6HPYfCxfWRq3T7On99x/VyJ5OTtp/E2upp815yUi7p6E2cl4b97QXuJEkSZIkFTm0zyyuWBGWI0fC/Plw/PFtPKwytWYNnHFG7vDugAGlf84VK3J1htqo9Zo1YRlrnVSdoXZ7GpKtda31NBTuP5KoMxTWutbqDMn3NNRmre3p0krrb2Kt9zT4N7FUzHnJaYOePrTJ4qhRYTl6NFx/fYv/84o2aRI8/XR4PHt26Z9v1KjarDPkap1UnaE2az1pUlgmWetarDMk29NQu7VOq6ehNmttTycj6b+Jtd7T4N/EUjPnJaOVPd3yyeLcuXDzzeHxsmXQLvkzWd9++226xQ+AJ625GQYPDo/vvx/OOad0zxVrnVKdoz179tCxY8fknzjW+v77w3qpal0GPb1161aOPPLIxJ8XCHWGXK2ruKf//Oc/A9DQ0MBhhx2W+PMn2tOQ+v5j7969/PWvfwWge5JXmkurpyHVffWmTZuy9e7bt28yT1pDPb19+3Y6d+4MkP7+o8p7+s0336ShoYF2afz/lFTOS6GnY+T/29/+Rvv2B77GZaIZO+mehkRr/W51hgTzdSt7uuVXQ33oIbjuuvA4wf+JN27cyNe+9jUAzjvvPF544QU+85nPADBixIjExkG7drl3JH7yk9I2d6x1CjvL1atX8y//8i8A9O/fnzvvvDPxMWRr/ZOfhPVS1Tqlnv7DH/4AwPXXX8+iRYvo27cv//qv/wrAmDFjEhtH9jXHWldhT69fv55x48axceNGAF5//XWmTJnCRRddlOg4aNcuvP6HHgrrpexpSG3/EY0fP576+noA/t//+3/JPXF8zbHWVdjT+WbNmsXPfvYzPv/5z3PmmWcm++Q10NNvvPEGU6ZM4eMf/zi//e1vAejUqRNf/epXEx1HQa2rsKeXL1/OHXfcAcAVV1zBnDlz+OQnP8lnP/vZRMeRWM5LuKdnzpzJN77xDQCmTp3KSSedVPD9GTNm8Otf/5qhQ4fy3//93wB873vfK+3EMT/nJdHT8TlLLNb6QHWOb+h973vf4xe/+AULFy4s+Xha29Ne4EaSJEmSVKRlp6E2NcExx8CGDWE93mspASNGjODGG28E4NJLL+XNN99kyL4bA7/yyit84AMfSGws2fuyNDbCm29Cp05t+/ObmsIy1jrBOkM4LL569Wq+8IUvAHDOOedkj3glbseOUGcoXa1T6umxY8cC8I//+I+ccMIJ3HLLLcyZMwcIR74SP/0m1roKe/qpp57iggsuoNO+1/WNb3yDF154gXnz5iU6DiC5noZUah299NJLXHPNNVx66aVAwkcWo1L2NBTuP1Ko87333gvAL3/5S5599lk6xHuXJa3Ke/qmm25i1KhRBWcinHjiifz617/mmDiupOT3NJT2b2KCdc5kMgwdOjR7ZPGSSy5h9+7dfOADH8gezT3xxBMTG08iOS/Bnt64cSMbN27M5uZly5Zlj3it2XexmU984hP88Y9/pGvXrkyZMgWA5557jp/97GclHVuiPQ0lrXU8eynWOr/O0cqVKwH4+c9/zk9/+lNeffXVko2nQCt6umWnoS5dCv36Jb6j/r//+z9efPHFbJAGOOaYY/jwhz8MwIIFC7jggguSG1B8/f36hZrEK++1laVLcz8/hQDSsWNHBgwYkPwfwQM54ohQByhdrVOo85tvvsnnP/95AD7+8Y8D8PWvf52HH34YgFdffZWBAwcmOqZsrauwp88777zsRBHgYx/7GBviH46kJdXT8blSsGvXLmbPns2nPvWpVJ4/q5Q9DantPwAWLVqUfRNvxYoV6U0Uoep7evXq1XTr1o2LLrqId955BwhvqnZJ4/5s+T0NVfM38fXXX+e3v/0tQ4cOzW47/PDDGTBgAD/+8Y8B+M53vpPcgJLIeQn2dM+ePWloaDjg92bNmgXAaaedRteuXQGyb4zcdtttNDc3l/bN6yrq6Z49ewIctNYAJ5xwAgB9+vQp+XgKtKKnWzZZXL4c8v5HTsrvfvc7unfvzuGHH16wPf4yFi1alOxkMRo6NNSkrRt7+fLcz1euDqWqdQp1PuaYY4om47169cruaD7ykY8kPiaganv6iH07yT179gDh8wQTJkxIZSxAVfZ0vu9///tcf/316XzWeX+l6mlItdZf/epXGTZsGADz5s3jpz/9KRdccEFB2E5UFff05z73Oa655hoGDBjA66+/DoQQfURKb8ZkexqqptY79h312Lp1KwAf+tCHABg8eDAr4i0P0lDKv4llkvGW7pukHX300dltMV/v2LEjmTevq7Cny9Yh9HTLJotbtkCSV7TbZ+nSpRx11FFF2+O2xYsXJz2koHv3UJO2Fn9mCrUuS7EOpap1mdT5xRdfZPS+S5WncgU4qOqe/p//+R8uv/xyAFatWsUJJ5zA17/+9XQGU6U9vWjRIiC8Y/pu76wmqlQ9DanVurm5mSVLlvCxj30MgL/7u7/jrbfe4owzzuA3v/kNQPZ7ianSngb4zGc+w+9//3uuvPJKrrzySiBcICQ1VdjTgwYN4kMf+lA2z8VT9+rq6rIXyUpFKf8mlkn2iJPFc/IuehKv4HnkkUfy8ssvl36yWIU9XbYOodZe4EaSJEmSVKTlt85Iwe7duw94n5J4b5LUjsJIbSSTyfDv//7vPPjgg2kPpWqdfPLJ2Qsl/Nu//Rt3330348aNS+9Usiqze/duZsyYAeQuvKLS+NOf/sSOHTuyn+EaOnQo5557LvPmzePJJ58EUjiyWMV27tzJ2rVr+eY3v8ndd98NwIc//OF0LtpUxW644YbsLbvat2/PW2+9xZw5c7j66qtTHll12717N8ABc3aHDh3SuaeoykrLZlk9esC2bSUaysEde+yxbNq0qWj7jh072LFjR/bDoonbti3UpK316JFarcvStm2lrXUZ1Pl73/set956Kz169KBHKV7n+1XlPd25c2c6d+7MN7/5TRoaGpgbb4qctCR6OuFaT548OXvFvfHjxzN+/HheeuklnnvuOZ577rn0rqhcqjpDaj195JFHAlBfX19wit6pp57Kr371K371q18lPqZq7Ono3nvv5ayzzuLOO+/kmWee4ZlnnuHee+9N77N0sc5V9jfx61//Oo8//jiPP/44mUyG0aNHs23bNkaNGsWoUaNSGVO19nS+Y4899l1zdv/+/Us/iCrt6bJ0CD3dssniwIGQwucDTz/9dP7yl7+wd+9e9u7dm92+bt061q1bx6BBgxIfExBqUYrzuAcOTK3WZWnx4tLWOuU6P/vssxx//PHZS1pD7kIsiauhnj7uuOPo1atXOk+eRE8nXOuPfexjnHjiiZx44ol069aNbt26UV9fT8eOHenYsWP2KnuJK1WdIbWe/uAHP0hjYyO/+93v+N3vfpfd3qVLFz7wgQ8keyupqAp7OvrP//xPTj75ZADOP/98zj//fEaMGMGzzz6byniyda7Cv4lnnnkmZ555JldffTVPPPEEw4YN46yzzuKss85KZ0BV2tP5Tj/9dE4//fSCyeKWLVvYsmUL77zzTjK3LKnini47h9DTnr8pSZIkSSrSss8snnIKrFqVu7FjQp/1+chHPsLIkSN55plnAPj7v/97mpqaePvtt4FwpbJExde/alWoSVuLPzPWOqXPVMX7SWUymVSeHwivf9Wq8LhUtU6hp4HsKUzPP/88V199NatXr2b79u0AzJ07l3/6p39KbCxArtZV2NN/+MMfCt4d3b59O126dEnnNgNJ9XR8roRq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\n",
      "text/plain": [
       "<Figure size 1152x576 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pomegranate time:  2.7319540977478027 ((), (), (), (), (), (3,), (), (1,), (), (), (), (), (7,), (11,), (13,))\n"
     ]
    }
   ],
   "source": [
    "tic = time.time()\n",
    "model = BayesianNetwork.from_samples(X, algorithm='exact')\n",
    "plt.figure(figsize=(16, 8))\n",
    "model.plot()\n",
    "plt.show()\n",
    "print(\"pomegranate time: \", time.time() - tic, model.structure)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It looks like we got three desirable attributes by using a constraint graph. The first is that there was over an order of magnitude speed improvement in finding the optimal graph. The second is that we were able to remove some edges we didn't want in the final Bayesian network, such as those between 11, 13, and 14. We also removed the edge between 1 and 12 and 1 and 3, which are spurious given the model that we originally defined. The third desired attribute is that we can specify the direction of some of the edges and get a better causal model.\n",
    "\n",
    "Lets take a look at how big of a model we can learn given a three layer constraint graph like before. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Y+zYsS912RgREdVvnIkiIiKqguzsbFy9ehX9+/fHRx99pOpyiIhIBXhPFBERERERURVwJoqIiIiIiKgKGuU9UTdv3iz3+SdUNfn5+RxHFeHYqw7HXnU49qrBcVcdjr3qcOxVo66Ne35+Ptzd3ctta5QhSltbGy4uLqouo96LioriOKoIx151OPaqw7FXDY676nDsVYdjrxp1bdyjoqIqbOPlfERERERERFXAEEVERERERFQFDFFERERERERVwBBFRERERERUBQxRREREREREVcAQRUREREREVAWNconzysjKykJqairkcrmqS6mz5HL5C5d+bEw0NDSgo6ODJk2aQEdHR9XlEBEREVENYogqR1ZWFh4+fAgbGxvo6upCJBKpuqQ6SSqVQldXV9VlqJwgCCgoKEB2djYkEgmsrKxgbGys6rKIiIiIqIYwRJUjNTUVNjY20NPTU3UpVA+IRCJoamrC1NQU2traSElJYYgiIiIiasB4T1Q55HI5Z1jopejq6iI/P1/VZRARERFRDWKIqgAv4aOXwc8NERERUcPHEEVERERERCpRJAg4nJqKTteuoWtqKg6lpqq6pErhPVFU6wRB4IwNERERUSNWUFSE/amp+EwiQVRurmL7rpQUDLO0VGFllcMQ1QiMGjUKV69erbA9KCgI48ePr/E6ZDIZVq5cic6dO6NPnz413h8RERER1S35RUX4JiUFoRIJYvLylNp0AExr3lw1hVURQ1Qj0aFDB8yZM6fcNmtr61qpITU1Fbt374aXl1et9EdEREREdUNuYSG2JydjVXw8EkotwmWoro4pNjYYIJWim5mZiiqsGoaoRsLIyAju7u6qLoOIiIiIGpGsggJsTkrC5/HxSJXLldrMNDQwrXlzTLWxgammJqKiolRUZdVxYQkCAIwfPx5eXl549OiRYtv//vc/9OjRA1lZWQCAyMhIfPDBB/Dy8oKrqysGDRqE/fv3Kx0nMTER06ZNg7e3N7y9vTF16lQkJSUhISEBfn5+AIBp06Zh1KhRtXdyRERERFSrMuRyBD94APuICMyNiVEKUFaamljZsiViO3fGInt7mGpqqrDSl8OZqEpaEx+P4NhYZBcWqqwGA3V1BNvbI8jWtsrvFQQBBQUF5bZpaGggJCQEb7zxBlauXImVK1fiu+++w4ULF7B9+3YYGRkhKSkJo0ePhq+vL9av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sWLFClgsFshauD22wWCAVqtt0X1eiUAAo+zu6+u/2ova2lqPOI4dEY+9eHjsxcNjLw4ed/Hw2IuHx14c7em4t2mISklJcTleXFyMoKAgqFQq21jnzp1hMplQUlKCsLCwFq1DpVIhMTGxRffZEWm1Wh5HkfDYi4fHXjw89uLgcRcPj714eOzF4WnHvbFAJ23DOtyqqamBUql0GLt032g0ilESERERERGRSx4RolQqlVNYunRfrVaLURIREREREZFLHhGiwsPDodfrHYJUcXExlEolgoKCRKyMiIiIiIjIkUeEqMTERCgUChw6dMg2dvDgQVxzzTWQy9v19YCJiIiIiMjLeESIUqvVGD9+PNLT0/H7779j9+7dWLNmDR566CGxSyMiIiIiInLgMdM8aWlpeOWVVzB16lT4+flh5syZuOuuu8Qui4iIiIiIyIFoIerEiRMO99VqNTIyMpCRkSFSRURERERERJfnEcv5iIiIiIiI2guGKCIiIiIiomZgiCIiIiIiImoGhigiIiIiIqJmkAiCIIhdRFs7fPgwVCqV2GUQEREREZGHMhgMGDBggMvHOmSIIiIiIiIiulJczkdERERERNQMDFFERERERETNwBBFRERERETUDAxRREREREREzcAQRURERERE1AwMUXRVXn75ZUyZMkXsMjoMk8mEhQsXYvDgwRg8eDDmzZsHo9EodlkdQnl5OZ5//nlcf/31uPnmm7FkyRJYLBaxy/JaRqMRd999N3788UfbWFlZGZ5++mkMGjQII0aMwJdffilihd7L1bE/duwYpkyZgoEDB2LEiBF47733YLVaRazSO7k69vamT5+O2bNnt3FV3s/Vca+srMTs2bORnJyMoUOH4u233wYbWrc8V8e+oKAAjz/+OJKTkzFixAisXbtWxArdY4iiK3bgwAF8/vnnYpfRoSxatAi7du3CihUrsHLlSnz33XdYvny52GV1COnp6SgqKsK6deuwePFibNmyxWN/sbd3BoMBzz33HLKyshzGZ8+ejbKyMmzcuBFPPvkk/u///g+//fabSFV6J1fHvqysDDNmzECvXr2wefNmzJ07F2vWrMH69etFrNT7uPv//pJNmzbhhx9+aOOqvJ+7456amoqTJ09i3bp1WLhwITZs2IBNmzaJVKV3cnfs//GPf0ClUmHTpk2YM2cOli1bhq+//lqkKt1jiKIrUl1djblz52LQoEFil9Jh6PV6bNy4EfPnz0dycjIGDRqEp556CseOHRO7tA5h3759mDp1Knr16oUbbrgBd999N3766Sexy/I6p06dwsSJE5GTk+MwnpOTg71792L+/PlISEjAX//6V9xzzz3YsGGDSJV6H3fHft++fZDL5XjppZcQHx+P4cOH4+GHH8ZXX30lUqXex92xv+TChQtYunQp+vbt28aVeTd3x/3UqVPYu3cvlixZgsTERAwbNgzTpk3DkSNHRKrU+7g79uXl5Th8+DAef/xxxMfHY9SoUbj55ps98t9bhii6IkuXLsX111+P66+/XuxSOoyDBw9CrVbjxhtvtI3de++9WL16tYhVdRzBwcH473//i5qaGhQVFeG7777DNddcI3ZZXueXX37B4MGD8emnnzqMHzlyBKGhoYiLi7ONJScn4/Dhw21dotdyd+yvv/56vPXWW5BK/3zLIJFIoNfr27pEr+Xu2F/yyiuvICUlBV27dm3bwrycu+P+008/oWfPnujWrZtt7Mknn8Rrr73W1iV6LXfH3sfHB2q1Gps3b4bJZEJ2djZ+++03JCUliVSpe3KxC6D259ChQ9i+fTu2bt2KNWvWiF1Oh5GTk4PIyEhs3boVq1atQnV1NUaPHo1nn30WSqVS7PK83rx585CamopBgwbBarXihhtuwN///nexy/I6KSkpLseLi4sRFhbmMNapUycUFha2RVkdgrtjHxERgYiICNv92tpafPbZZ7jlllvaqjSv5+7YA8C2bduQm5uLZcuWIS0trQ2r8n7ujntOTg6io6Px4YcfYt26dZBIJLjvvvswY8YMSCSSNq7SO7k79iqVCvPmzcOrr76K9evXw2KxYNy4cbjvvvvauMLL40wUNYvRaMRLL72EOXPmICgoSOxyOpSqqirk5eVh3bp1SE9PxyuvvIIdO3Zg8eLFYpfWIeTk5KBPnz5Yt24d3n//fZw/fx4ZGRlil9Vh1NTUOH1YoFQqYTKZeLJ3G7JYLHjhhRdQU1ODJ554QuxyvF5paSkWLFiA1157DQqFQuxyOoyqqir88ssvOHDgAN566y0899xz+OCDD/DRRx+JXVqHcObMGQwbNgz//ve/sXTpUuzfvx8ffvih2GU54UwUNcvy5csRFxeHO++8U+xSOhy5XI7KykosXrwYsbGxAOpOfE1NTUVaWprD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\n",
      "text/plain": [
       "<Figure size 1008x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "constraint_times, times = [], []\n",
    "\n",
    "x = numpy.arange(1, 7)\n",
    "for i in x:\n",
    "    symptoms = tuple(range(i))\n",
    "    diseases = tuple(range(i, i*2))\n",
    "    genetic = tuple(range(i*2, i*3))\n",
    "\n",
    "    constraints = networkx.DiGraph()\n",
    "    constraints.add_edge(genetic, diseases)\n",
    "    constraints.add_edge(diseases, symptoms)\n",
    "    \n",
    "    X = numpy.random.randint(2, size=(2000, i*3))\n",
    "    \n",
    "    tic = time.time()\n",
    "    model = BayesianNetwork.from_samples(X, algorithm='exact', constraint_graph=constraints)\n",
    "    constraint_times.append( time.time() - tic )\n",
    "    \n",
    "    tic = time.time()\n",
    "    model = BayesianNetwork.from_samples(X, algorithm='exact')\n",
    "    times.append( time.time() - tic )  \n",
    "\n",
    "\n",
    "plt.figure(figsize=(14, 6))\n",
    "plt.title('Time To Learn Bayesian Network', fontsize=18)\n",
    "plt.xlabel(\"Number of Variables\", fontsize=14)\n",
    "plt.ylabel(\"Time (s)\", fontsize=14)\n",
    "plt.xticks(fontsize=14)\n",
    "plt.yticks(fontsize=14)\n",
    "plt.plot( x*3, times, linewidth=3, color='c', label='Exact')\n",
    "plt.plot( x*3, constraint_times, linewidth=3, color='m', label='Constrained')\n",
    "plt.legend(loc=2, fontsize=16)\n",
    "plt.yscale('log')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Looks like by including a constraint graph, we can far more quickly find the optimal Bayesian network. This can allow us to create Bayesian networks on dozens of variables as long as we can order them into layers.\n",
    "\n",
    "## Other Parameters\n",
    "\n",
    "There are three other parameters that are worth mentioning. The first is that a vector of weights can be passed in alongside a matrix of samples, with each entry in the vector corresponding to the weight of that sample. By default all weights are set to 1, but they can be any non-negative number.\n",
    "\n",
    "```\n",
    "model = BayesianNetwork.from_samples(X, weights=weights)\n",
    "```\n",
    "\n",
    "Next is the pseudocounts parameter that indicates the number added to the observations of each observed variable combination. This acts as a regularizer by smoothing over the counts and is typically used to prevent the model from saying it is impossible for a combination of variables to occur together just because they weren't observed in the data. Currently all learning algorithms support pseudocounts. By default this is set to 0.\n",
    "\n",
    "```\n",
    "model = BayesianNetwork.from_samples(X, pseudocount=1.7\n",
    "```\n",
    "\n",
    "Lastly, the maximum number of parents that each variable can have can be limited. This is sometimes referred to as the k-learn problem in literature. In practice this can dramatically speed up the BNSL task as the majority of time is spent determining the best parent sets. Currently this only affects the exact and greedy algorithm as in the Chow-Liu algorithm each variable only has a single parent.\n",
    "\n",
    "```\n",
    "model = BayesianNetwork.from_samples(X, algorithm='exact', max_parents=2)\n",
    "```\n",
    "\n",
    "Since exact inference uses minimum description length as a score function, the maximum number of parents is by default set to $\\log \\left(\\frac{n}{\\log(n)} \\right)$ with $n$ being the number of samples in the dataset.\n",
    "\n",
    "# Conclusions\n",
    "\n",
    "pomegranate currently supports exact BNSL through an a shortest path dynamic programming algorithm, an A\\* algorithm, a greedy algorithm, the Chow-Liu tree building algorithm, and a constraint-graph based algorithm which can significantly speed up structure learning if you have any prior knowledge of the interactions between variables.\n",
    "\n",
    "If you have any suggestions for how to improve pomegranate or ideas for algorithms to implement, feel free to open an issue on the issue tracker! I'd love to hear feedback."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
